package com.uum.oss.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.img.Img;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.uum.oss.pojo.entity.OssUpload;
import com.uum.oss.pojo.page.OssPage;
import com.uum.oss.pojo.vo.OssCatalogVO;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.imageio.stream.FileImageOutputStream;
import javax.imageio.stream.ImageOutputStream;
import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.*;
import java.util.*;
import java.util.List;


@Service
@ConfigurationProperties(prefix = "aliyun.oss")
@Slf4j
public class OssService {

    @Setter
    private String endpoint;
    @Setter
    private String keyId;
    @Setter
    private String keySecret;
    @Setter
    private String bucketName;




    @SneakyThrows
    public List<String> uploadFile(OssUpload upload) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, keyId, keySecret);
        // 上传文件流。
        List<String> urlList = new ArrayList<>();
        for (MultipartFile file : upload.getFileData()) {
            InputStream inputStream = file.getInputStream();
            if (upload.getIsScale() == 1) {
                //裁剪照片大小高200 宽200
                Img scale = Img.from(inputStream).scale(200, 200);
                inputStream = ImgUtil.toStream(scale.getImg(), "png");
            }

            String filename = file.getOriginalFilename().replaceAll(" ","");
            String timePath = DateUtil.formatDate(new Date());
            //目录 ➕ 时间 ➕ UUID ➕ 文件名
            String catalog = upload.getCatalog();
            catalog = StrUtil.isNotBlank(catalog) == true ? catalog : "other";
            filename = catalog + "/" + timePath + "/" + IdUtil.fastSimpleUUID() + filename ;
            ossClient.putObject(bucketName, filename, inputStream);
            //把上传文件后的路径返回
            //手动拼接返回路径
            //https://maybe-blog.oss-cn-shenzhen.aliyuncs.com/avatar/2020-09-19/672cc422-432d-403d-a33e-59584e75b49cfile.png
            String url = "https://" + bucketName + "." + endpoint + "/" + filename;
            urlList.add(url);
            inputStream.close();
        }
        // 关闭OSSClient。
        ossClient.shutdown();
        return urlList;
    }

    public List<OssCatalogVO> listOssCatalog() {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, keyId, keySecret);

        // 构造ListObjectsRequest请求。
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);

        // 列举文件。
        ObjectListing listing = ossClient.listObjects(listObjectsRequest);
        Set set = new HashSet();
        // 遍历所有文件。
        for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
            String key = objectSummary.getKey();
            String parent = key.substring(0, key.indexOf("/"));
            set.add(parent);
        }
        List<OssCatalogVO> list = packingTree(set);

        // 关闭OSSClient。
        ossClient.shutdown();
        return list;
    }

    //组装成父子
    private List<OssCatalogVO> packingTree(Set set) {
        List<OssCatalogVO> list = new ArrayList<>();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            OssCatalogVO vo = new OssCatalogVO();
            String next = String.valueOf(iterator.next());
            vo.setLabel(next);
            vo.setValue(next);

            // 创建OSSClient实例。
            OSS ossClient = new OSSClientBuilder().build(endpoint, keyId, keySecret);

            // 构造ListObjectsV2Request请求。
            ListObjectsV2Request listObjectsV2Request = new ListObjectsV2Request(bucketName);

            // 设置prefix参数来获取fun目录下的所有文件与文件夹。
            listObjectsV2Request.setPrefix(next + "/");

            // 设置正斜线（/）为文件夹的分隔符。
            listObjectsV2Request.setDelimiter("/");

            // 发起列举请求。
            ListObjectsV2Result result = ossClient.listObjectsV2(listObjectsV2Request);

            List<OssCatalogVO> temp = new ArrayList();
            // 遍历commonPrefix。
            // commonPrefixs列表中显示的是fun目录下的所有子文件夹。由于fun/movie/001.avi和fun/movie/007.avi属于fun文件夹下的movie目录，因此这两个文件未在列表中。
            for (String commonPrefix : result.getCommonPrefixes()) {
                OssCatalogVO children = new OssCatalogVO();
                int first = commonPrefix.indexOf("/");                                  //第一次出现/的下标位置
                int second = commonPrefix.indexOf("/", first + 1);         //第二次出现/的下标的位置
                String value = commonPrefix.substring(first + 1, second);
                children.setValue(value);
                children.setLabel(value);
                temp.add(children);
            }
            vo.setChildren(temp);
            list.add(vo);
            // 关闭OSSClient。
            ossClient.shutdown();
        }
        return list;
    }

    public List<String> page(OssPage page) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, keyId, keySecret);
        // 指定每页列举200个文件。
        final int maxKeys = 200;
        ListObjectsV2Result result = null;
        String nextContinuationToken = null;
        List<String> resultList = new ArrayList();
        // 分页列举指定前缀的文件。
        // 分页列举，每次传入上次返回结果中的nextContinuationToken。
        do {
            ListObjectsV2Request listObjectsV2Request = new ListObjectsV2Request(bucketName).withMaxKeys(maxKeys);
            listObjectsV2Request.setContinuationToken(nextContinuationToken);
            if (!StringUtils.isEmpty(page.getCatalog())) {
                listObjectsV2Request.setPrefix(page.getCatalog());
            }
            // 发起列举请求。
            result = ossClient.listObjectsV2(listObjectsV2Request);
            for (OSSObjectSummary sums : result.getObjectSummaries()) {
                String key = sums.getKey();
                String substring = key.substring(key.indexOf("/") + 1);
                if (!substring.equals("")) {
                    //拼接url地址
                    resultList.add("https://" + bucketName + "." + endpoint + "/" + sums.getKey());
                }
            }
            nextContinuationToken = result.getNextContinuationToken();
        } while (result.isTruncated());
        // 关闭OSSClient。
        ossClient.shutdown();
        return resultList;
    }

    public List<String> deletePictureBatch(List<String> ids) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, keyId, keySecret);

        // 删除文件。key等同于ObjectName，表示删除OSS文件时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg。
        List<String> keys = new ArrayList<>();
        for (String item : ids) {
            keys.add(item);
        }

        DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(new DeleteObjectsRequest(bucketName).withKeys(keys));
        List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();

        // 关闭OSSClient。
        ossClient.shutdown();
        return deletedObjects;
    }

    public void addOssCatalog(String catalogName) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, keyId, keySecret);
        ossClient.putObject(bucketName, catalogName + "/demo.png", ResourceUtil.getStreamSafe("uploadfile/demo.png"));
        // 关闭OSSClient。
        ossClient.shutdown();
    }
}
